#include <windows.h>
#include <iomanip>
#include <sstream>
#include <string>
#include <vector>
#include <direct.h>
#include <shlobj.h>
#include <winbase.h>
#include <lmcons.h>
#define ID_EDIT 101

// 全局变量
HWND hEdit;
std::vector<std::string> commandHistory;
int historyPos = 0;
std::string currentDir;
std::string userName;
static std::string terminal_init_promt = "redis-terminal-cli> ";

// 获取当前用户名
std::string GetUserName() {
    char username[UNLEN + 1];
    DWORD usernameLen = UNLEN + 1;
    if (GetUserNameA(username, &usernameLen)) {
        return std::string(username);
    }
    return "";
}

// 获取当前目录
std::string GetCurrentDirectory() {
    char cwd[1024];
    if (_getcwd(cwd, sizeof(cwd))) {
        return std::string(cwd);
    }
    return "";
}

// 自定义环境变量获取函数（使用 getenv 替代 _dupenv_s）
bool GetEnvVar(const char* varName, std::string& result) {
    const char* envValue = std::getenv(varName);
    if (envValue != nullptr) {
        result = envValue;
        return true;
    }
    return false;
}

// 命令处理函数
void ExecuteCommand(const std::string& command) {
    if (command.empty()) return;

    std::string result;
    std::vector<std::string> args;
    std::istringstream iss(command);
    std::string token;

    while (iss >> token) {
        args.push_back(token);
    }

    if (args.empty()) return;

    if (args[0] == "cd") {
        if (args.size() < 2) {
            std::string homeDir;
            if (GetEnvVar("USERPROFILE", homeDir)) {
                _chdir(homeDir.c_str());
            }
        } else {
            if (_chdir(args[1].c_str()) != 0) {
                result = "Error: Cannot change directory\r\n";
            }
        }
        currentDir = GetCurrentDirectory();
        result = "Current directory: " + currentDir + "\r\n";
    }
    // 可以添加更多命令处理逻辑
    // 这里简单将命令和结果输出到编辑框
    std::string output = command + "\r\n" + result;
    int len = GetWindowTextLength(hEdit);
    SendMessage(hEdit, EM_SETSEL, len, len);
    SendMessage(hEdit, EM_REPLACESEL, FALSE, (LPARAM)output.c_str());
    // 显示新的提示符
    std::string prompt = userName + "@" + currentDir + "> ";
    len = GetWindowTextLength(hEdit);
    SendMessage(hEdit, EM_SETSEL, len, len);
    SendMessage(hEdit, EM_REPLACESEL, FALSE, (LPARAM)prompt.c_str());

    // 滚动到编辑框底部
    SendMessage(hEdit, EM_LINESCROLL, 0, INT_MAX);
}

LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) {
    switch (uMsg) {
        case WM_CREATE: {
            // 获取用户名和当前目录
            userName = GetUserName();
            currentDir = GetCurrentDirectory();

            // 获取字体高度
            HFONT hFont = CreateFontW(
                    16, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE,
                    DEFAULT_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS,
                    DEFAULT_QUALITY, FIXED_PITCH, L"Courier New");
            TEXTMETRIC tm;
            HDC hdc = GetDC(hwnd);
            SelectObject(hdc, hFont);
            GetTextMetrics(hdc, &tm);
            ReleaseDC(hwnd, hdc);
            int lineHeight = tm.tmHeight;
            int halfLineHeight = lineHeight / 2;

            // 创建编辑框，将 x 坐标设为 0，y 坐标设为 0.5 行间距，并添加垂直滚动条
            hEdit = CreateWindow("EDIT", "",
                                 WS_CHILD | WS_VISIBLE | WS_BORDER | ES_MULTILINE | ES_AUTOVSCROLL | ES_AUTOHSCROLL | WS_VSCROLL,
                                 0, halfLineHeight, 800, 500 - halfLineHeight,
                                 hwnd, (HMENU)ID_EDIT, NULL, NULL);

            // 设置编辑框样式
            SetWindowLongPtr(hEdit, GWL_EXSTYLE, GetWindowLongPtr(hEdit, GWL_EXSTYLE) | WS_EX_CLIENTEDGE);

            SendMessage(hEdit, WM_SETFONT, (WPARAM)hFont, TRUE);

            // 设置编辑框左右边距
            SendMessage(hEdit, EM_SETMARGINS, EC_LEFTMARGIN | EC_RIGHTMARGIN, MAKELPARAM(10, 10));

            // 设置编辑框上下边距
            RECT rect;
            GetClientRect(hEdit, &rect);
            rect.top += halfLineHeight;
            rect.bottom -= halfLineHeight;
            SendMessage(hEdit, EM_SETRECT, 0, (LPARAM)&rect);

            SetWindowText(hEdit, terminal_init_promt.c_str());
            break;
        }
        case WM_COMMAND: {
            if (HIWORD(wParam) == EN_CHANGE && (HWND)lParam == hEdit) {
                // 编辑框内容改变时的处理
                int len = GetWindowTextLength(hEdit);
                if (len > 0) {
                    char buffer[1024];
                    GetWindowText(hEdit, buffer, len + 1);
                    std::string text(buffer);
                    if (text.back() == '\n') {
                        len = GetWindowTextLength(hEdit);
                        SendMessage(hEdit, EM_SETSEL, len, len);
                        SendMessage(hEdit, EM_REPLACESEL, FALSE, (LPARAM)terminal_init_promt.c_str());
                    }
                }
            }
            break;
        }
        case WM_KEYDOWN: {
            if ((HWND)lParam == hEdit) {
                switch (wParam) {
                    case VK_RETURN: {
                        // 获取编辑框中的最后一行文本作为命令
                        int len = GetWindowTextLength(hEdit);
                        char buffer[1024];
                        GetWindowText(hEdit, buffer, len + 1);
                        std::string text(buffer);
                        size_t lastLineStart = text.rfind('\n');
                        if (lastLineStart == std::string::npos) {
                            lastLineStart = 0;
                        } else {
                            lastLineStart++;
                        }
                        std::string command = text.substr(lastLineStart + (terminal_init_promt).length());

                        // 执行命令
                        ExecuteCommand(command);

                        // 将命令添加到历史记录
                        commandHistory.push_back(command);
                        historyPos = commandHistory.size();
                        break;
                    }
                    case VK_UP: {
                        if (historyPos > 0) {
                            historyPos--;
                            std::string command = commandHistory[historyPos];
                            int len = GetWindowTextLength(hEdit);
                            size_t lastLineStart = 0;
                            std::string text;
                            if (len > 0) {
                                char buffer[1024];
                                GetWindowText(hEdit, buffer, len + 1);
                                text = buffer;
                                lastLineStart = text.rfind('\n');
                                if (lastLineStart == std::string::npos) {
                                    lastLineStart = 0;
                                } else {
                                    lastLineStart++;
                                }
                            }
                            std::string newText = text.substr(0, lastLineStart) + terminal_init_promt + command;
                            SetWindowText(hEdit, newText.c_str());
                            SendMessage(hEdit, EM_SETSEL, -1, -1);
                        }
                        break;
                    }
                    case VK_DOWN: {
                        if (historyPos < static_cast<int>(commandHistory.size()) - 1) {
                            historyPos++;
                            std::string command = commandHistory[historyPos];
                            int len = GetWindowTextLength(hEdit);
                            size_t lastLineStart = 0;
                            std::string text;
                            if (len > 0) {
                                char buffer[1024];
                                GetWindowText(hEdit, buffer, len + 1);
                                text = buffer;
                                lastLineStart = text.rfind('\n');
                                if (lastLineStart == std::string::npos) {
                                    lastLineStart = 0;
                                } else {
                                    lastLineStart++;
                                }
                            }
                            std::string newText = text.substr(0, lastLineStart) + terminal_init_promt + command;
                            SetWindowText(hEdit, newText.c_str());
                            SendMessage(hEdit, EM_SETSEL, -1, -1);
                        } else if (historyPos == static_cast<int>(commandHistory.size()) - 1) {
                            historyPos++;
                            int len = GetWindowTextLength(hEdit);
                            size_t lastLineStart = 0;
                            std::string text;
                            if (len > 0) {
                                char buffer[1024];
                                GetWindowText(hEdit, buffer, len + 1);
                                text = buffer;
                                lastLineStart = text.rfind('\n');
                                if (lastLineStart == std::string::npos) {
                                    lastLineStart = 0;
                                } else {
                                    lastLineStart++;
                                }
                            }
                            std::string newText = text.substr(0, lastLineStart) + terminal_init_promt;
                            SetWindowText(hEdit, newText.c_str());
                            SendMessage(hEdit, EM_SETSEL, -1, -1);
                        }
                        break;
                    }
                }
            }
            break;
        }
        case WM_DESTROY:
            PostQuitMessage(0);
            break;
        default:
            return DefWindowProc(hwnd, uMsg, wParam, lParam);
    }
    return 0;
}

// 主函数
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) {
    // 注册窗口类
    WNDCLASS wc = {};
    wc.lpfnWndProc = WindowProc;
    wc.hInstance = hInstance;
    wc.lpszClassName = "TerminalWindowClass";
    wc.hbrBackground = (HBRUSH)(COLOR_WINDOW);
    wc.hCursor = LoadCursor(NULL, IDC_ARROW);

    RegisterClass(&wc);

    // 创建窗口
    HWND hwnd = CreateWindowEx(
            0, "TerminalWindowClass", "Windows Terminal Emulator",
            WS_OVERLAPPEDWINDOW,
            CW_USEDEFAULT, CW_USEDEFAULT, 800, 500,
            NULL, NULL, hInstance, NULL);

    if (hwnd == NULL) {
        return 0;
    }

    // 显示窗口
    ShowWindow(hwnd, nCmdShow);

    // 消息循环
    MSG msg = {};
    while (GetMessage(&msg, NULL, 0, 0)) {
        TranslateMessage(&msg);
        DispatchMessage(&msg);
    }

    return 0;
}